package com.hsqyz.esp32_led.common.helper;

import cn.hutool.core.util.HexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * Netty 辅助工具类
 *
 * @author lcz
 */
@Data
@NoArgsConstructor
public class NettyHelper {

    /**
     * 将单个字节转换为其8位二进制字符串形式。
     *
     * @param byteValue 单个字节的值
     * @return 该字节的8位二进制字符串表示
     */
    public static String byteToBinaryString(byte byteValue) {
        StringBuilder binaryStr = new StringBuilder(8);
        for (int i = 7; i >= 0; i--) {
            binaryStr.append((byteValue >>> i) & 1);
        }
        return binaryStr.toString();
    }


    /**
     * 将一个字节转换为十六进制字符串。
     * 此方法用于将单个字节数据转换为其十六进制表示形式的字符串。这对于在处理二进制数据时提供可读性非常有用，
     * 比如在调试或数据表示时。
     *
     * @param singleByte 待转换的字节数据。
     * @return 字节的十六进制字符串表示形式。字符串长度为2，始终包含两个十六进制数字。
     */
    public static String byteToHexString(byte singleByte) {
        return HexUtil.toHex(singleByte);
    }


    /**
     * 将字节数组转换为十六进制字符串。
     * 此方法用于将二进制数据表示为更易读的十六进制字符串形式。
     *
     * @param bytes 输入的字节数组，代表要转换的原始二进制数据。
     * @return 转换后的十六进制字符串。每个字节被转换为两个十六进制字符。
     */
    public static String bytesToHexString(byte[] bytes) {
        return HexUtil.encodeHexStr(bytes);
    }


    /**
     * 从 ByteBuf 中获取指定长度字节的 byte数组
     *
     * @param byteBuf    byteBuf，不能为null，且必须有足够的可读字节
     * @param byteLength 字节长度，必须大于等于0
     * @return 指定长度的字节数组
     * @throws IllegalArgumentException  如果 byteBuf 为null或 byteLength 小于0
     * @throws IndexOutOfBoundsException 如果 byteLength 大于 byteBuf 的剩余可读字节长度
     */
    public static byte[] getSpecifiedLengthBytes(ByteBuf byteBuf, int byteLength) throws IllegalArgumentException, IndexOutOfBoundsException {
        // 参数校验，验证byteBuf是否为null。
        if (byteBuf == null) {
            throw new IllegalArgumentException("byteBuf cannot be null.");
        }
        // 长度校验，验证指定的byteLength是否小于0。
        if (byteLength < 0) {
            throw new IllegalArgumentException("byteLength must be greater than or equal to 0.");
        }
        // 检查是否有足够的可读字节，确保ByteBuf中的剩余可读字节大于等于指定的byteLength。
        if (byteBuf.readableBytes() < byteLength) {
            throw new IndexOutOfBoundsException("Not enough bytes in byteBuf to read " + byteLength + " bytes.");
        }

        // 创建一个新的字节数组，长度为指定的byteLength，并从ByteBuf中读取字节到该数组。
        byte[] bytes = new byte[byteLength];
        byteBuf.readBytes(bytes); // 由于进行了参数和边界检查，此时调用是安全的
        return bytes;
    }


    /**
     * 将ByteBuf中的指定长度字节转换为十六进制表示的字符串。
     * 允许通过参数指定输出字符串中的字母（A-F/a-f）是否为大写。
     *
     * @param byteBuf   原始的ByteBuf对象，需包含足够的可读字节。
     * @param length    要转换的字节长度，必须为正数且不超过ByteBuf的可读字节数。
     * @param uppercase 若为true，则输出大写字母(A-F)；若为false，则为小写字母(a-f)。
     * @return 转换后的十六进制字符串，根据uppercase参数决定大小写。
     * @throws IllegalArgumentException 如果byteBuf为null、length非法或ByteBuf中可读字节不足。
     */
    public static String toHexString(ByteBuf byteBuf, int length, boolean uppercase) {
        // 参数有效性检查
        if (byteBuf == null || length <= 0 || byteBuf.readableBytes() < length) {
            throw new IllegalArgumentException("Invalid input parameters.");
        }
        // 从ByteBuf中安全地读取指定长度的数据
        ByteBuf slice = byteBuf.readSlice(length);
        // 转换为十六进制字符串，并根据参数调整字母大小写
        String hexString = ByteBufUtil.hexDump(slice);
        return uppercase ? hexString.toUpperCase() : hexString.toLowerCase();
    }


    /**
     * 将ByteBuf中的字节转换为对应的整数。
     * <p>
     * 此方法根据指定的字节长度（1、2或4字节），从ByteBuf中读取字节并转换为整数。
     * 这种转换是必要的，因为ByteBuf的读取方法（如readByte、readShort、readInt）
     * 返回的类型可能是原始类型byte、short或int，而此方法的返回类型是Integer。
     * <p>
     * 方法通过抛出异常来处理无效输入：
     * - 如果byteBuf为null，则抛出NullPointerException。
     * - 如果byteLength不是1、2、4之一，则抛出IllegalArgumentException。
     *
     * @param byteBuf    要读取的ByteBuf对象，不能为空。
     * @param byteLength 指定的字节长度，必须是1、2、4。
     * @return 从ByteBuf中读取并转换为Integer类型的整数。
     * @throws NullPointerException     如果byteBuf为null。
     * @throws IllegalArgumentException 如果byteLength不是1、2、4。
     */
    public static Integer toInteger(ByteBuf byteBuf, Integer byteLength) {
        // 参数校验：非空检查
        if (byteBuf == null) {
            throw new NullPointerException("byteBuf cannot be null.");
        }
        // 参数校验：确保byteLength为1、2或4
        if (!(byteLength == 1 || byteLength == 2 || byteLength == 4)) {
            // 使用IllegalArgumentException代替RuntimeException，明确byteLength的有效范围
            throw new IllegalArgumentException("byteLength 必须是 1、2 或 4");
        }
        // 根据byteLength的值进行相应操作
        if (byteLength == 1) {
            return (int) byteBuf.readByte();
        } else if (byteLength == 2) {
            return (int) byteBuf.readShort();
        } else {
            return byteBuf.readInt();
        }
    }


}
